/**
 * @file        gtd.hpp
 * @brief       Defines specific methods related with todo items.
 *
 * @author      Emre Turkay <emreturkay at gmail>
 * @date        May.31.2008
 *
 * Copyright Emre Turkay 2009
 * Distributed under the Boost Software License, Version 1.0.
 * (See accompanying file COPYRIGHT or copy at
 * http://www.boost.org/LICENSE_1_0.txt)
 */

#ifndef _GTD_HPP_
#define _GTD_HPP_

#include "done.hpp"
#include "projects.hpp"

#include <boost/date_time/posix_time/posix_time.hpp>
#include <boost/optional.hpp>
#include <boost/none.hpp>

#include <stdexcept>
#include <string>
#include <list>
#include <iterator>
#include <algorithm>
#include <fstream>
#include <sstream>
#include <vector>

namespace gtd
{

    /*
     * Exceptions.
     */

    /// The GTD backend.
    struct gtd
    {
        /// Unique id for a project.
        typedef size_t project_id;
        /// The container data type for the projects.
        typedef std::map<project_id, project> projects;

        /// Constructor, initializes the GTD backend.
        gtd();

        /// Writes the done items to the given ostream.
        void save_done(std::ostream& os);

        /// Getter method for a project.
        project& get_project(project_id index);

        /// Const getter method for a project.
        const project& get_project(project_id index) const;

        /// Marks the top item of the project as done.
        void done(project_id index);

        /// Cancels the top item of the project.
        void cancel(project_id index);

        /// Defers the top item of the project.
        void defer(project_id index);

        /// Clear all the internal data.
        void clear();

        /// Parse and append the given item to the projects.
        void append(const std::string& value);

        /// Parse and prepend the given item to the projects.
        void prepend(const std::string& value);

        /// Move the top item of the given project to the bottom of the queue.
        void move_back(project_id index);

        /// Returns true if there is no item at all.
        bool empty() const;

        /// Returns the list of project ids.
        std::list<project_id> project_ids() const;

        /// Return the list of project ids having the given context.
        std::list<project_id> project_ids(const std::string& ctx) const;

        /// Returns the name of the project with given id.
        const boost::optional<std::string>& project_name(project_id id) const;

        /// Returns the list of action ids of the project with given id.
        std::list<project::action_id> items(project_id id) const;

        /// Returns an action.
        const action& item(project_id id, project::action_id index) const;

        /// Returns the item count of the given project.
        size_t item_count(project_id id) const;

        /// Searches the projects by name.
        boost::optional<project_id> find_project(const std::string& name) const;

        /// Clear the done items container.
        void clear_done();

        /// Load done items from the given istream.
        void load_done(std::istream& is);

        /// Returns the set of all done items (ordered by timestamp).
        const std::set<done_item>& done_items() const;

        /// Returns the list of done items in the given time duration.
        std::set<done_item> done_items(boost::gregorian::date_duration d) const;

        /// Load todo items from the given file.
        void load_todo(const std::string& filename);

        /// Load done items from the given file.
        void load_done(const std::string& filename);

        /// Save the todo items into the given file and create a backup.
        void save_todo(const std::string& filename, const std::string& backup);

        /// Save the done items into the given file.
        void save_done(const std::string& filename);

    private:
        /// Creates a new project with the given name.
        project_id create_project(boost::optional<std::string> name);

    private:
        /// The projects container.
        projects projects_;
        /// The project ids (the order).
        std::list<project_id> list_;
        /// The done items container.
        std::set<done_item> done_items_;
    };

} // namespace gtd

#endif // _GTD_HPP_
